我們需要根據id找到對應的項目,把它的done屬性改成相反值。
注意:要用不可變更新的方式,不能直接改陣列。
const toggleTodo=(id)=>{
setTodos(prev=>
prev.map(todo=>
todo.id===id ? { ...todo, done:!todo.done } : todo
)
)
}
用filter移除指定id的項目:
const removeTodo=(id)=>{
setTodos(prev=>prev.filter(todo=>todo.id!==id))
}
import { useState } from 'react'
export default function TodoApp(){
const [text,setText] = useState("")
const [todos,setTodos] = useState([
{ id:1, text:"學React", done:false }
])
const addTodo=(e)=>{
e.preventDefault()
const title=text.trim()
if(!title) return
setTodos(prev=>[...prev,{ id:Date.now(), text:title, done:false }])
setText("")
}
const toggleTodo=(id)=>{
setTodos(prev=>prev.map(todo=>
todo.id===id ? { ...todo, done:!todo.done } : todo
))
}
const removeTodo=(id)=>{
setTodos(prev=>prev.filter(todo=>todo.id!==id))
}
return (
<div className="p-6 space-y-3">
<form onSubmit={addTodo} className="flex gap-2">
<input
className="border rounded px-3 py-2 flex-1"
placeholder="輸入待辦事項"
value={text}
onChange={e=>setText(e.target.value)}
/>
<button className="px-4 py-2 rounded bg-blue-600 text-white">新增</button>
</form>
<ul className="space-y-2">
{todos.map(todo=>(
<li
key={todo.id}
className="flex items-center justify-between p-2 border rounded"
>
<span
onClick={()=>toggleTodo(todo.id)}
className={`flex-1 cursor-pointer ${
todo.done ? "line-through text-gray-400" : ""
}`}
>
{todo.text}
</span>
<button
className="ml-3 text-red-600"
onClick={()=>removeTodo(todo.id)}
>
刪除
</button>
</li>
))}
</ul>
</div>
)
}